package com.atguigu.gmall.product.service.impl;

import com.atguigu.gmall.common.cache.GmallCache;
import com.atguigu.gmall.common.config.constant.MqCons;
import com.atguigu.gmall.common.constant.RedisConst;
import com.atguigu.gmall.model.product.*;
import com.atguigu.gmall.product.mapper.*;
import com.atguigu.gmall.product.service.ManageService;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.redisson.api.RedissonClient;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 平台管理中心
 */
@Service
public class ManageServiceImpl implements ManageService {

    @Autowired
    private Category1Mapper category1Mapper;
    @Autowired
    private Category2Mapper category2Mapper;
    @Autowired
    private Category3Mapper category3Mapper;
    @Autowired
    private BaseAttrInfoMapper baseAttrInfoMapper;
    @Autowired
    private BaseAttrValueMapper baseAttrValueMapper;
    @Autowired
    private SpuInfoMapper spuInfoMapper;
    @Autowired
    private BaseSaleAttrMapper baseSaleAttrMapper;
    @Autowired
    private BaseTrademarkMapper baseTrademarkMapper;
    @Autowired
    private SpuImageMapper spuImageMapper;
    @Autowired
    private SpuSaleAttrMapper spuSaleAttrMapper;
    @Autowired
    private SpuSaleAttrValueMapper spuSaleAttrValueMapper;
    @Autowired
    private SkuInfoMapper skuInfoMapper;

    @Override
    public List<BaseCategory1> getCategory1() {
        return category1Mapper.selectList(null);
    }

    @Override
    public List<BaseCategory2> getCategory2(Long category1Id) {
        return category2Mapper.selectList(new QueryWrapper<BaseCategory2>().eq("category1_id", category1Id));
    }

    @Override
    public List<BaseCategory3> getCategory3(Long category2Id) {
        return category3Mapper.selectList(new QueryWrapper<BaseCategory3>().eq("category2_id", category2Id));
    }

    @Override
    public List<BaseAttrInfo> attrInfoList(Long category1Id, Long category2Id, Long category3Id) {

        return baseAttrInfoMapper.attrInfoList(category1Id, category2Id, category3Id);
    }

    @Override
    public void saveAttrInfo(BaseAttrInfo baseAttrInfo) {

        if (null != baseAttrInfo.getId()) {
            //修改
            baseAttrInfoMapper.updateById(baseAttrInfo);
            //删除之前的
            baseAttrValueMapper.delete(new QueryWrapper<BaseAttrValue>().eq("attr_id", baseAttrInfo.getId()));
        } else {
            //添加
            baseAttrInfoMapper.insert(baseAttrInfo);
        }

        baseAttrInfo.getAttrValueList().forEach(v -> {
            v.setAttrId(baseAttrInfo.getId());
            baseAttrValueMapper.insert(v);
        });

    }

    @Override
    public List<BaseAttrValue> getAttrValueList(Long attrId) {
        return baseAttrValueMapper.selectList(new QueryWrapper<BaseAttrValue>().eq("attr_id", attrId));
    }

    @Override
    public IPage<SpuInfo> getSpuInfoByPage(Integer page, Integer limit, Long category3Id) {

        return spuInfoMapper.selectPage(new Page<>(page, limit),
                new QueryWrapper<SpuInfo>().eq("category3_id", category3Id)
        );
    }

    @Override
    public List<BaseSaleAttr> baseSaleAttrList() {
        return baseSaleAttrMapper.selectList(null);
    }

    @Override
    public List<BaseTrademark> getTrademarkList() {
        return baseTrademarkMapper.selectList(null);
    }

    @Override
    public void saveSpuInfo(SpuInfo spuInfo) {

        spuInfoMapper.insert(spuInfo);

        spuInfo.getSpuImageList().forEach(i -> {
            i.setSpuId(spuInfo.getId());
            spuImageMapper.insert(i);
        });

        spuInfo.getSpuSaleAttrList().forEach(s -> {
            s.setSpuId(spuInfo.getId());
            spuSaleAttrMapper.insert(s);
            s.getSpuSaleAttrValueList().forEach(v -> {
                v.setSpuId(spuInfo.getId());
                v.setSaleAttrName(s.getSaleAttrName());
                spuSaleAttrValueMapper.insert(v);
            });
        });


    }

    @Override
    public IPage<SkuInfo> skuList(Integer page, Integer limit) {
        IPage<SkuInfo> page1 = new Page(page, limit);
        return skuInfoMapper.selectPage(page1, null);
    }

    @Override
    public List<SpuSaleAttr> spuSaleAttrList(Long spuId) {

//            List<SpuSaleAttr> spuSaleAttrList = spuSaleAttrMapper.
//                selectList(new QueryWrapper<SpuSaleAttr>().eq("spu_id", spuId));
//
        return spuSaleAttrMapper.getSaleAttrListAndSaleAttrValeList(spuId);
    }

    @Override
    public List<SpuImage> spuImageList(Long spuId) {
        return spuImageMapper.selectList(new QueryWrapper<SpuImage>().eq("spu_id", spuId));
    }

    @Autowired
    private SkuImageMapper skuImageMapper;
    @Autowired
    private SkuAttrValueMapper skuAttrValueMapper;
    @Autowired
    private SkuSaleAttrValueMapper skuSaleAttrValueMapper;

    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private RedissonClient redissonClient;

    @Override
    public void saveSkuInfo(SkuInfo skuInfo) {

        skuInfoMapper.insert(skuInfo);

        skuInfo.getSkuImageList().forEach(i -> {
            i.setSkuId(skuInfo.getId());
            skuImageMapper.insert(i);

        });
        skuInfo.getSkuAttrValueList().forEach(a -> {
            a.setSkuId(skuInfo.getId());
            skuAttrValueMapper.insert(a);
        });
        skuInfo.getSkuSaleAttrValueList().forEach(s -> {
            s.setSkuId(skuInfo.getId());
            s.setSpuId(skuInfo.getSpuId());
            skuSaleAttrValueMapper.insert(s);
        });

    }

    @Override
    public void cancelSale(Long skuId) {
        SkuInfo skuInfo = new SkuInfo();
        skuInfo.setId(skuId);
        skuInfo.setIsSale(0);
        skuInfoMapper.updateById(skuInfo);

        rabbitTemplate.convertAndSend(
                MqCons.EXCHANGE_DIRECT_GOODS,
                MqCons.ROUTING_GOODS_LOWER,skuId);
    }

    @Autowired
    private RabbitTemplate rabbitTemplate;
    @Override
    public void onSale(Long skuId) {
        SkuInfo skuInfo = new SkuInfo();
        skuInfo.setId(skuId);
        skuInfo.setIsSale(1);
        skuInfoMapper.updateById(skuInfo);

        rabbitTemplate.convertAndSend(
                MqCons.EXCHANGE_DIRECT_GOODS,
                MqCons.ROUTING_GOODS_UPPER,skuId);

    }

    //    @Override
//    public SkuInfo getSkuInfoById(Long skuId) {
//
//        //1：判断缓存中是否有SkuInfo   sku:1:info
//        String key = RedisConst.SKUKEY_PREFIX + skuId + RedisConst.SKUKEY_SUFFIX;
//        SkuInfo skuInfo = (SkuInfo) redisTemplate.opsForValue().get(key);
//        if(null == skuInfo){
//            skuInfo = getSkuInfoDB(skuId);
//            //保存缓存一份
//            redisTemplate.opsForValue().set(key,skuInfo);
//        }
//
//        return skuInfo;
//
//    }
//    @Override
//    @GmallCache(prefix = "sku") //将来保存在Redis中的时候  使用此前缀+ skuId 作为Key    Value值是 SkuInfo
//    public SkuInfo getSkuInfoById(Long skuId) {
//
//        try {
//            String key = RedisConst.SKUKEY_PREFIX + skuId + RedisConst.SKUKEY_SUFFIX;
//            SkuInfo skuInfo = (SkuInfo) redisTemplate.opsForValue().get(key);
//
//            //判断缓存是否存在
//            if (null == skuInfo) {
//                //不存在 ：上锁
//                //使用Redis  Redisson   缓存三大问题 ： 穿透 雪崩 击穿
//                RLock lock = redissonClient.getLock("lock");
//                boolean res = lock.tryLock(RedisConst.SKULOCK_EXPIRE_PX1, RedisConst.SKULOCK_EXPIRE_PX2, TimeUnit.SECONDS);
//                if (res) {
//                    //获取到了锁
//                    try {
//                        //查询数据库
//                        skuInfo = getSkuInfoDB(skuId);
//                        if (null == skuInfo) {
//                            //此时就是穿透
//                            SkuInfo skuInfo1 = new SkuInfo();
//                            redisTemplate.opsForValue().set(skuId, skuInfo1, RedisConst.SECKILL__TIMEOUT, TimeUnit.SECONDS);
//                            return skuInfo1;
//                        } else {
//                            redisTemplate.opsForValue().set(skuId, skuInfo, RedisConst.SECKILL__TIMEOUT, TimeUnit.SECONDS);
//                            return skuInfo;
//                        }
//                    } catch (Exception e) {
//                        e.getStackTrace();
//                    } finally {
//                        //解锁
//                        lock.unlock();
//                    }
//                } else {
//                    //直接查询数据库
//                    return getSkuInfoDB(skuId);
//                }
//
//            }
//        } catch (Exception e) {
//            e.getStackTrace();
//        }
//        return getSkuInfoDB(skuId);
//    }
    @Override
    @GmallCache(prefix = RedisConst.SKUKEY_PREFIX) //将来保存在Redis中的时候  使用此前缀+ skuId 作为Key    Value值是 SkuInfo
    public SkuInfo getSkuInfoById(Long skuId) {
        System.out.println("进入方法中");
        return getSkuInfoDB(skuId);
    }

    public SkuInfo getSkuInfoDB(Long skuId) {
        SkuInfo skuInfo = skuInfoMapper.selectById(skuId);
        skuInfo.setSkuImageList(skuImageMapper.selectList(new QueryWrapper<SkuImage>().eq("sku_id", skuId)));
        return skuInfo;
    }

    @Autowired
    private BaseCategoryViewMapper baseCategoryViewMapper;

    @Override
    @GmallCache(prefix = RedisConst.CATEGORYKEY_PREFIX)
    public BaseCategoryView getCategoryView(Long category3Id) {
        return baseCategoryViewMapper.selectById(category3Id);
    }

    @Override
    public BigDecimal getPrice(Long skuId) {
        SkuInfo skuInfo = skuInfoMapper.selectById(skuId);
        if (null != skuInfo) {
            return skuInfo.getPrice();
        } else {
            return new BigDecimal(0);
        }

    }

    @Override
    @GmallCache(prefix = RedisConst.SPUSALEATTRLISTCHECKBYSKU_PREFIX)
    public List<SpuSaleAttr> getSpuSaleAttrListCheckBySku(Long skuId, Long spuId) {
        return spuSaleAttrMapper.getSpuSaleAttrListCheckBySku(skuId, spuId);
    }

    @Override
    @GmallCache(prefix = RedisConst.SKUVALUEIDSMAP_PREFIX)
    public Map getSkuValueIdsMap(Long spuId) {
        Map map = new HashMap();
        List<Map> listMap = skuSaleAttrValueMapper.getSkuValueIdsMap(spuId);
        if (!CollectionUtils.isEmpty(listMap)) {
            listMap.forEach(m -> {
                map.put(m.get("value_ids"), m.get("sku_id"));
            });
        }
        return map;
    }

    @Override
    public List<Map> getBaseCategoryList() {

        List<Map> result = new ArrayList<>();

        List<BaseCategoryView> baseCategoryViewList
                = baseCategoryViewMapper.selectList(null);

        Map<Long, List<BaseCategoryView>> listMap1 = baseCategoryViewList.stream().
                collect(Collectors.groupingBy(BaseCategoryView::getCategory1Id));

        int index = 1;
        Set<Map.Entry<Long, List<BaseCategoryView>>> entries1 = listMap1.entrySet();

        for (Map.Entry<Long, List<BaseCategoryView>> entry1 : entries1) {

            List<BaseCategoryView> value1 = entry1.getValue();

            Map map1 = new HashMap();
            map1.put("index",index);
            map1.put("categoryId",entry1.getKey());

            map1.put("categoryName", value1.get(0).getCategory1Name());

            List<Map> result1 = new ArrayList<>();

            Map<Long, List<BaseCategoryView>> listMap2 = value1.stream().
                    collect(Collectors.groupingBy(BaseCategoryView::getCategory2Id));

            Set<Map.Entry<Long, List<BaseCategoryView>>> entries2 = listMap2.entrySet();

            for (Map.Entry<Long, List<BaseCategoryView>> entry2 : entries2) {
                Map map2 = new HashMap();
                map2.put("categoryId",entry2.getKey());
                map2.put("categoryName",entry2.getValue().get(0).getCategory2Name());

                List<BaseCategoryView> value2 = entry2.getValue();
                List<Map> result2 = new ArrayList<>();
                value2.forEach(v -> {
                    Map map3 = new HashMap();
                    map3.put("categoryId",v.getCategory3Id());
                    map3.put("categoryName",v.getCategory3Name());
                    result2.add(map3);
                });
                map2.put("categoryChild",result2);

                result1.add(map2);
            }
            map1.put("categoryChild",result1);

            result.add(map1);

        }
        return result;
    }
    @Override
    public BaseTrademark getTrademarkByTmId(Long tmId) {
        return baseTrademarkMapper.selectById(tmId);
    }

    @Override
    public List<SkuAttrValue> getAttrList(Long skuId) {

        return skuAttrValueMapper.selectSkuAttrValueListBySkuId(skuId);
    }

}
